package com.linkoog.devtools.intellij.ui;

import com.intellij.ui.dsl.gridLayout.*;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.ApiStatus;

import javax.swing.*;
import java.util.*;

import static java.lang.Math.max;

@ApiStatus.Experimental
public class RowsGridBuilder {

    private static final int GRID_EMPTY = -1;

    private final JComponent panel;
    private final GridLayout layout;
    private final Grid grid;
    private int columnsCount = 0;
    private final Set<Integer> resizableColumns;
    private HorizontalAlign defaultHorizontalAlign = HorizontalAlign.LEFT;
    private VerticalAlign defaultVerticalAlign = VerticalAlign.CENTER;
    private boolean defaultBaselineAlign = false;
    private int x = 0;
    private int y = GRID_EMPTY;

    public RowsGridBuilder(JComponent panel, Grid grid) {
        this.panel = panel;
        this.layout = (GridLayout) panel.getLayout();
        this.grid = grid != null ? grid : layout.getRootGrid();
        this.resizableColumns = this.grid.getResizableColumns();
    }

    public int getColumnsCount() {
        return columnsCount;
    }

    public Set<Integer> getResizableColumns() {
        return resizableColumns;
    }

    public RowsGridBuilder columnsGaps(List<UnscaledGapsX> value) {
        grid.getColumnsGaps().clear();
        grid.getColumnsGaps().addAll(value);
        return this;
    }

    public RowsGridBuilder row(UnscaledGapsY rowGaps, boolean resizable) {
        x = 0;
        y++;
        setRowGaps(rowGaps);

        if (resizable) {
            resizableRow();
        }
        return this;
    }

    public RowsGridBuilder cell(JComponent component,
                                int width,
                                HorizontalAlign horizontalAlign,
                                VerticalAlign verticalAlign,
                                boolean baselineAlign,
                                boolean resizableColumn,
                                UnscaledGaps gaps,
                                UnscaledGaps visualPaddings,
                                String widthGroup,
                                ComponentHelper componentHelper) {
        if (y == GRID_EMPTY) {
            y = 0;
        }
        if (resizableColumn) {
            addResizableColumn();
        }

        Constraints constraints = new Constraints(grid, x, y, width,1, horizontalAlign, verticalAlign, baselineAlign,
                gaps, visualPaddings, widthGroup, componentHelper);
        panel.add(component, constraints);
        return skip(width);
    }

    public Constraints constraints(int width,
                                   HorizontalAlign horizontalAlign,
                                   VerticalAlign verticalAlign,
                                   boolean baselineAlign,
                                   UnscaledGaps gaps,
                                   UnscaledGaps visualPaddings,
                                   String widthGroup,
                                   ComponentHelper componentHelper) {
        if (y == GRID_EMPTY) {
            y = 0;
        }
        Constraints result = new Constraints(grid, x, y, width,1, horizontalAlign, verticalAlign, baselineAlign,
                gaps, visualPaddings, widthGroup, componentHelper);
        skip(width);
        return result;
    }

    public Grid subGrid(int width,
                        HorizontalAlign horizontalAlign,
                        VerticalAlign verticalAlign,
                        boolean baselineAlign,
                        boolean resizableColumn,
                        UnscaledGaps gaps,
                        UnscaledGaps visualPaddings) {
        startFirstRow();
        if (resizableColumn) {
            addResizableColumn();
        }

        Constraints constraints = new Constraints(grid, x, y, width,1, horizontalAlign, verticalAlign, baselineAlign,
                gaps, visualPaddings, null, null);
        skip(width);
        return layout.addLayoutSubGrid(constraints);
    }

    public RowsGridBuilder subGridBuilder(int width,
                                          HorizontalAlign horizontalAlign,
                                          VerticalAlign verticalAlign,
                                          boolean baselineAlign,
                                          boolean resizableColumn,
                                          UnscaledGaps gaps,
                                          UnscaledGaps visualPaddings) {
        return new RowsGridBuilder(panel, subGrid(width, horizontalAlign, verticalAlign, baselineAlign, resizableColumn, gaps, visualPaddings))
                .defaultHorizontalAlign(defaultHorizontalAlign)
                .defaultVerticalAlign(defaultVerticalAlign)
                .defaultBaselineAlign(defaultBaselineAlign);
    }

    public RowsGridBuilder skip(int count) {
        x += count;
        columnsCount = max(columnsCount, x);
        return this;
    }

    public void setRowGaps(UnscaledGapsY rowGaps) {
        startFirstRow();

        while (grid.getRowsGaps().size() <= y) {
            grid.getRowsGaps().add(UnscaledGapsY.EMPTY);
        }
        grid.getRowsGaps().set(y, rowGaps);
    }

    private RowsGridBuilder defaultHorizontalAlign(HorizontalAlign defaultHorizontalAlign) {
        this.defaultHorizontalAlign = defaultHorizontalAlign;
        return this;
    }

    private RowsGridBuilder defaultVerticalAlign(VerticalAlign defaultVerticalAlign) {
        this.defaultVerticalAlign = defaultVerticalAlign;
        return this;
    }

    private RowsGridBuilder defaultBaselineAlign(boolean defaultBaselineAlign) {
        this.defaultBaselineAlign = defaultBaselineAlign;
        return this;
    }

    public RowsGridBuilder resizableRow() {
        startFirstRow();
        grid.getResizableRows().add(y);
        return this;
    }

    public void addResizableColumn() {
        grid.getResizableColumns().add(x);
    }

    private void startFirstRow() {
        if (y == GRID_EMPTY) {
            y = 0;
        }
    }
}


